#include <locale.h>
#include <stdio.h>
#include <stdint.h>
#include <windows.h>
#include <process.h>
#include <assert.h>
#include <TCHAR.h>
#include <time.h>

// simulate mcu functions ---------------------------------------------------------------------------------
#include "CH58x_common.h"
#include "simu_mcu582.h"

static const char* zy_m0_eeprom = ".\\app\\user_data\\zy_m0_eeprom.dat";
static const char* zy_m0_flash = ".\\app\\user_data\\zy_m0_flash.dat";
char* simu_uart0_str = (char*)_T("\\\\.\\COM30");
char* simu_uart1_str = (char*)_T("\\\\.\\COM32");
char* simu_uart2_str = (char*)_T("\\\\.\\COM34");

void __WFE(void) {};
void DelayUs(int x) {};
uint8_t simu_r8_wake_flag = 0;
void PWR_PeriphWakeUpCfg(FunctionalState s, uint8_t perph, WakeUP_ModeypeDef mode) 
{
    simu_r8_wake_flag = (s != 0) ? simu_r8_wake_flag | (1 << perph) : simu_r8_wake_flag & ~(1 << perph);
    return;
}

void SetSysClock(int x) { return; }
void HSECFG_Capacitance(HSECapTypeDef c);
void DelayMs(int x) { Sleep(x); }
void LClk32K_Select(int x) { return; }
void PFIC_EnableIRQ(int x) { return; }
void SYS_RecoverIrq(uint32_t irq_status) { return; }
void WWDG_ResetCfg(int x) { ; }
void HSECFG_Current(int x) { ; }
uint8_t RTC_GetITFlag(RTC_EVENTTypeDef f) { return 1; }
void Calibration_LSI(int x) { ; }
int GetSysClock(void) { return 0; }

void SYS_DisableAllIrq(uint32_t* pirqv) { ; } // 关中断。
void SYS_ResetExecute(void) { ; }  //软件复位MCU

void WWDG_ITCfg(FunctionalState s){};
uint32_t FLASH_EEPROM_CMD(uint8_t cmd, uint32_t StartAddr, void* Buffer, uint32_t Length){};
void sys_safe_access_enable(void){};
void sys_safe_access_disable(void) {};
void TMR0_TimerInit(uint32_t t) {};
void PFIC_DisableIRQ(IRQn_Type IRQn) {};
uint8_t IWDG_Enable(IWDG_32K_PR pr, uint16_t rlr) { return 0; }
void PowerMonitor(FunctionalState s, VolM_LevelypeDef vl) {};
uint32_t RTC_GetCycle32k(void) { return 0; }
void HSECFG_Capacitance(HSECapTypeDef c) { ; }

SimuHWData simu_hw;         // 模拟硬件数据, 由模拟器周期下发
unsigned char simu_register[1024] = { 0 };

void GPIOPinRemap(int x, int y) { ; }


// 
void DllPrintf(char* fmt, ...)
{
    //不定参数格式化
    va_list argptr;
    va_start(argptr, fmt);
    char buffer[512] = { 0 };
    //char *p = va_arg(argptr, char*);
    int cnt = vsprintf(buffer, fmt, argptr);
    va_end(argptr);
    //sprintf(buffer, "[%s:%u-%s]: xxxx\r\n", __FILE__, __LINE__, __FUNCTION__);

    //建立控制台窗口
    static HANDLE gHConsole = INVALID_HANDLE_VALUE;
    if (INVALID_HANDLE_VALUE == gHConsole) {
        //AllocConsole();
        gHConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    }
    //打印到指定的控制台窗口
    DWORD dw;
    //WriteConsole(gHConsole, buffer, strlen(buffer), &dw, NULL);
    WriteConsoleA(gHConsole, buffer, strlen(buffer), &dw, NULL);

    return;
}

// simu eeprom read/write
static uint8_t simu582_eeprom_data[32 * 1024] = { 0 };  // 32K
static simu_eeprom(void)
{
    FILE* fp = NULL;
    static int flag = 0;
    if (!flag) {
        fp = fopen(zy_m0_eeprom, "rb");
        if (fp != NULL) {
            fread(simu582_eeprom_data, 1, 32 * 1024, fp);
        }
        else {
            _mkdir(".\\app");
            _mkdir(".\\app\\user_data");
            fp = fopen(zy_m0_eeprom, "wb+");
            fwrite(simu582_eeprom_data, 1, 32 * 1024, fp);
        }       
    }
    if (fp) {
        fclose(fp);
        flag = 1;
    }
}
void EEPROM_READ(uint32_t StartAddr, uint8_t* Buffer, int Length)
{
    simu_eeprom();
    assert((StartAddr % 4) == 0);
    memcpy(Buffer, simu582_eeprom_data + StartAddr, Length);
}
void EEPROM_ERASE(uint32_t StartAddr, int Length)
{
    simu_eeprom();
    assert((StartAddr % 4) == 0);
    memset(simu582_eeprom_data + StartAddr, 0xff, Length);
    FILE *fp = fopen(zy_m0_eeprom, "wb+");
    fwrite(simu582_eeprom_data, 1, 32 * 1024, fp);
    if (fp) fclose(fp);
}
void EEPROM_WRITE(uint32_t StartAddr, uint8_t* Buffer, int Length)
{
    simu_eeprom();
    assert((StartAddr % 4) == 0);
    memcpy(simu582_eeprom_data + StartAddr, Buffer, Length);
    FILE* fp = fopen(zy_m0_eeprom, "wb+");
    fwrite(simu582_eeprom_data, 1, 32 * 1024, fp);
    if (fp) fclose(fp);
}
// simu flash read/write
uint8_t simu582_flash_data[448 * 1024] = { 0 };  // 448K Flash
static simu_flash(void)
{
    FILE* fp = NULL;
    static int flag = 0;
    if (!flag) {
        fp = fopen(zy_m0_flash, "rb");
        if (fp != NULL) {
            fread(simu582_flash_data, 1, 32 * 1024, fp);
        }
        else {
            fp = fopen(zy_m0_flash, "wb+");
            fwrite(simu582_flash_data, 1, 32 * 1024, fp);
        }
    }
    if (fp) {
        fclose(fp);
        flag = 1;
    }
}
void FLASH_ROM_READ(uint32_t StartAddr, uint8_t* Buffer, int Length)
{
    simu_flash();
    assert((StartAddr % 4) == 0);
    memcpy(Buffer, simu582_flash_data + StartAddr, Length);
}
void FLASH_ROM_ERASE(uint32_t StartAddr, int Length)
{
    simu_flash();
    //assert((StartAddr % 4) == 0);
    memset(simu582_flash_data + StartAddr, 0xff, Length);
    FILE* fp = fopen(zy_m0_flash, "wb+");
    fwrite(simu582_flash_data, 1, 448 * 1024, fp);
    if (fp) fclose(fp);
}
void FLASH_ROM_WRITE(uint32_t StartAddr, uint8_t* Buffer, int Length)
{
    simu_flash();
    assert(((size_t)Buffer % 4) == 0);
    memcpy(simu582_flash_data + StartAddr, Buffer, Length);
    FILE* fp = fopen(zy_m0_flash, "wb+");
    fwrite(simu582_flash_data, 1, 448 * 1024, fp);
    if (fp) fclose(fp);
}


// simu buzzor
void ThreadSimuBuzzor(void)
{
    Beep(2000, 1000);
    Sleep(3600*1000);
}
void SimuBuzzor(int isOn)
{
    static HANDLE beep_h = NULL;
    // TODO 修改为开关控制。
    if (isOn) {
        if(beep_h == NULL)
            beep_h = _beginthread(ThreadSimuBuzzor, 0, NULL);
    }
    else {
        if (beep_h) {
            Beep(0, 0);
            TerminateThread(beep_h, 0);
            CloseHandle(beep_h);
            beep_h = NULL;
        }
    }
        
}

int rtc_tmr = 0;
void RTC_TMRFunCfg(int x) {
    switch (x) {
        case Period_0_125_S:
            rtc_tmr = 125;
            break;
        case Period_0_25_S:
            rtc_tmr = 250;
            break;
        case Period_0_5_S:
            rtc_tmr = 500;
            break;
        case Period_1_S:
            rtc_tmr = 1000;
            break;
        case Period_2_S:
            rtc_tmr = 2000;
            break;
        case Period_4_S:
            rtc_tmr = 4000;
            break;
        case Period_8_S:
            rtc_tmr = 8000;
            break;
        case Period_16_S:
            rtc_tmr = 16000;
            break;
    }
    return;
}
int simu_sleep_ms = 0;
void LowPower_Sleep(uint8_t rm)
{
    simu_sleep_ms = rtc_tmr;
    for (int i = 0; i < simu_sleep_ms; i += 25) {
        DbgTask();
        Sleep(25);
    }
}

// 模拟打印log时输出时间
const char* GetLocalTimeStrWin32(void)
{
    static char buf[24];
    time_t t = time(NULL);
    struct tm* tt = localtime(&t);
    tt->tm_year += 1900;
    tt->tm_mon += 1;
    int ms = t % 1000;
    sprintf(buf, "%04d/%02d/%02d-%02d:%02d:%02d:%03d", tt->tm_year, tt->tm_mon, tt->tm_mday, tt->tm_hour, tt->tm_min, tt->tm_sec, ms);
    return buf;
}








// ------------------------------------------------------------------------------------------------
// PC Simulator interface ---------------------------------------------------------------------------------

void GetMACAddress(uint8_t* buf)
{
    for (uint8_t i = 0; i < 6; i++)
        buf[i] = i;
}


void RTC_InitTime(uint16_t y, uint16_t mon, uint16_t d, uint16_t h, uint16_t m, uint16_t s) {};
void RTC_GetTime(uint16_t* py, uint16_t* pmon, uint16_t* pd, uint16_t* ph, uint16_t* pm, uint16_t* ps)
{
    time_t t = time(NULL);
    struct tm* tt = localtime(&t);
    *py= tt->tm_year + 1900;
    *pmon = tt->tm_mon += 1;
    *pd = tt->tm_mday;
    *ph = tt->tm_hour;
    *pm = tt->tm_min;
    *ps = tt->tm_sec;
}


void LClk32K_Cfg(LClk32KTypeDef hc, FunctionalState s)
{
    return;
}
void ADC_InterBATSampInit(void)
{
    return;
}
